﻿// ----------------------------------------------------------------------------
// macros.h
// ----------------------------------------------------------------------------
/*
 Description:
 機種依存判定を行うためのベースクラス、基本的なマクロ. 
 */
#pragma once
#include <fw/base/core/config.h>

#if defined(__cplusplus)
#include <cstddef>  // std::size_t 
#else
#include <stddef.h>
#endif

// デバッグオプション
#if defined(_DEBUG) || defined(DEBUG)
#define FW_DEBUG 						ON
#endif

#ifdef NDEBUG
#define FW_NDEBUG						ON
#endif

#if defined(FW_DEBUG) && !defined(FW_DISABLE_UNIT_TEST)
#define FW_ENABLE_UNIT_TEST				ON
#endif

// ターゲット
#if defined(_WIN32) || defined(_WIN64)
#define FW_TARGET_WINDOWS				ON
#endif

#if defined(__APPLE__)
#define FW_TARGET_APPLE                 ON
#endif

#if defined (_WIN64) || (__x86_64__)
#define FW_TARGET_64BIT					ON
#elif defined (_WIN32) || (__i386__)
#define FW_TARGET_32BIT					ON
#endif

// 各種コンパイラ宣言の違いを吸収する.
#if defined(_MSC_VER)
#define FW_COMPILER_MSC					ON
#define FW_COMPILER_MSVC				ON
#endif

#if defined(__GNUC__)
#define FW_COMPILER_GCC					ON
#define FW_COMPILER_GNUC				ON
#endif

#if defined(__clang__)
#define FW_COMPILER_CLANG				1
#endif

#if defined(FW_COMPILER_MSC)
	#define FW_FORCE_INLINE					__forceinline
	#define FW_NO_INLINE					__declspec(noinline)
	#define FW_FASTCALL						__fastcall
	#define FW_PLATFORM_DEBUG_BREAK()       __debugbreak()
//	#define FW_ALIGNOF(x)					__alignof(x)
#elif defined(FW_COMPILER_GCC) || defined(FW_COMPILER_CLANG)
	#define FW_FORCE_INLINE					inline __attribute__((always_inline))
	#define FW_NO_INLINE					__attribute__((noinline))
	#define FW_FASTCALL						__attribute__((fastcall))
	#define FW_PLATFORM_DEBUG_BREAK()       __builtin_trap()
//	#define FW_ALIGNOF(x)					alignof(x)
#endif

// 任意の型の境界を調べる. 
#if defined(__cplusplus)
template <typename T> class FwAlignof
{
	struct Helper { char a_; T b_; };
public:
	static const std::size_t value = offsetof(Helper, b_);
};
#define FW_ALIGNOF(_type)	FwAlignof<_type>::value
#else
#define FW_ALIGNOF(_type)	offsetof(struct{char a; _type b;}, b)
#endif // __cplusplus 

// 関数の成功、失敗
#define FW_OK							1
#define FW_NG							0
#define FW_SUCCESS						FW_OK
#define FW_FAILURE						FW_NG
#define FW_TRUE							1
#define FW_FALSE						!(FW_TRUE)
#define FW_BOOL							int

// 未使用変数
#define FW_UNUSED(var)					(void)(var)

// 文字列を結合する. 直接 FW_CONCAT_IMPL を使わずに FW_CONCAT を使うこと.
#define FW_CONCAT_IMPL(x,y)				x ## y
#define FW_CONCAT(x,y)					FW_CONCAT_IMPL(x,y)
// 文字列リテラルを結合する. 
#define FW_CONCAT_STRING_IMPL(x,y)		(x y)
#define FW_CONCAT_STRING(x,y)			W_CONCAT_STRING_IMPL(x,y)

// 文字列化を行う. 直接 FW_STR_IMPL を使わずに FW_STR を使うこと. 
#define FW_STR_IMPL(x)					#x
#define FW_STR(x)						FW_STR_IMPL(x)

// 機種依存マクロ
#if USING(FW_COMPILER_GCC) || USING(FW_COMPILER_CLANG)
#define FW_THREAD_LS 					__thread
#define FW_LIKELY(cond) 				__builtin_expect(!!(cond), 1)
#define FW_UNLIKELY(cond) 				__builtin_expect((cond), 0)
#define FW_CACHELINE_SIZE				32 // 機種依存
#define FW_CACHELINE_ALIGNED 			__attribute__((aligned(FW_CACHELINE_SIZE)))
#define FW_FUNCTION						__PRETTY_FUNCTION__
#endif /* FW_COMPILER_GCC */
#if USING(FW_COMPILER_MSC) || USING(FW_COMPILER_MSVC)
#define FW_THREAD_LS					__declspec(thread)
#define FW_LIKELY(cond) 				(cond)
#define FW_UNLIKELY(cond) 				(cond)
#define FW_CACHELINE_SIZE				16
#define FW_CACHELINE_ALIGNED			__declspec(align(FW_CACHELINE_SIZE))
#define FW_FUNCTION						__FUNCSIG__
#endif /* FW_COMPILER_MSC */

// 静的な配列の数.
#define FW_ARRAY_SIZE(a)				(sizeof(a)/sizeof(a[0]))

// 静的なアラインメント値.
#define FW_ALIGNMENT(value, align)		((value)+(-(value)&((align)-1)))

// foreach 
#define FW_FOREACH( _iterator, _collectionObject, _collectionType ) \
for( _collectionType::iterator _iterator = _collectionObject.begin(); _iterator != _collectionObject.end(); ++_iterator )

// const foreach
#define FW_FOREACH_CONST( _iterator, _collectionObject, _collectionType ) \
for( _collectionType::const_iterator _iterator = _collectionObject.begin(); _iterator != _collectionObject.end(); ++_iterator )

// foreach in reverse 
#define FW_FOREACH_REVERSE( _iterator, _collectionObject, _collectionType ) \
for( _collectionType::reverse_iterator _iterator = _collectionObject.rbegin(); _iterator != _collectionObject.rend(); ++_iterator )

// const foreach in reverse
#define FW_FOREACH_CONST_REVERSE( _iterator, _collectionObject, _collectionType ) \
for( _collectionType::const_reverse_iterator _iterator = _collectionObject.rbegin(); _iterator != _collectionObject.rend(); ++_iterator )

// foreach with function call (use std::algorithm)
#define FW_FOREACH_CALL_FUNCTOR( _collectionObject, _functor ) \
for_each( _collectionObject.begin(), _collectionObject.end(), _functor )

// foreach with function call (use std::algorithm)
#define FW_FOREACH_CALL_FUNCTOR_REVERSE( _collectionObject, _functor ) \
for_each( _collectionObject.rbegin(), _collectionObject.rend(), _functor )

// sprintf 
#define FW_SPRINTF			sprintf_s

// 実装内部で利用している各種設定. 
#include <fw/base/core/_IMPL/internal_config.h>
